package com.xiguaji.tiktok.v1.web.tiktok.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.ObjectUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xiguaji.boot.toolkit.HttpUtil;
import com.xiguaji.boot.toolkit.JsonUtil;
import com.xiguaji.boot.toolkit.jdbc.JdbcTemplateHelper;
import com.xiguaji.boot.toolkit.jdbc.Page;
import com.xiguaji.tiktok.utils.CheckMobile;
import com.xiguaji.tiktok.utils.Ret;
import com.xiguaji.tiktok.utils.jwt.JwtUtil;
import com.xiguaji.tiktok.v1.common.dto.RegionResponse;
import com.xiguaji.tiktok.v1.common.model.General;
import com.xiguaji.tiktok.v1.common.service.CommonService;
import com.xiguaji.tiktok.v1.product.dto.PlatformTypeEnum;
import com.xiguaji.tiktok.v1.product.dto.ReportTypeEnum;
import com.xiguaji.tiktok.v1.product.service.ProductService;
import com.xiguaji.tiktok.v1.tiktok.aweme.dto.AwemeResponse;
import com.xiguaji.tiktok.v1.tiktok.blogger.dto.BloggerDataResponse;
import com.xiguaji.tiktok.v1.tiktok.blogger.dto.BloggerPerformanceResponse;
import com.xiguaji.tiktok.v1.tiktok.blogger.model.Blogger;
import com.xiguaji.tiktok.v1.tiktok.blogger.model.BloggerType;
import com.xiguaji.tiktok.v1.tiktok.blogger.service.BloggerService;
import com.xiguaji.tiktok.v1.tiktok.challenge.dto.ChallengeResponse;
import com.xiguaji.tiktok.v1.tiktok.challenge.dto.SearchData;
import com.xiguaji.tiktok.v1.tiktok.challenge.service.ChallengeService;
import com.xiguaji.tiktok.v1.tiktok.comparison.dto.BloggerResponse;
import com.xiguaji.tiktok.v1.tiktok.comparison.dto.RowData;
import com.xiguaji.tiktok.v1.tiktok.comparison.model.ComparisonHistory;
import com.xiguaji.tiktok.v1.tiktok.comparison.service.ComparisonService;
import com.xiguaji.tiktok.v1.tiktok.permission.repository.UserRoleRepository;
import com.xiguaji.tiktok.v1.tiktok.ranking.model.Ranking;
import com.xiguaji.tiktok.v1.tiktok.ranking.service.RankingService;
import com.xiguaji.tiktok.v1.user.dto.UserReturnDto;
import com.xiguaji.tiktok.v1.user.model.User;
import com.xiguaji.tiktok.v1.user.service.UserService;
import com.xiguaji.tiktok.v1.web.Tab;
import com.xiguaji.tiktok.v1.web.tiktok.dto.BloggerDto;
import com.xiguaji.tiktok.v1.web.tiktok.dto.BloggerPerformanceDto;
import com.xiguaji.tiktok.v1.web.tiktok.dto.SortDto;
import com.xiguaji.tiktok.v1.web.tiktok.dto.SoundResponse;
import com.xiguaji.tiktok.v1.web.tiktok.service.TopTiktokService;
import com.xiguaji.tiktok.v1.web.tiktok.service.TopTiktokSoundService;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;


@Controller
//@ConditionalOnClass(name="redisObjectTemplate")
public class TopTikTokController {
    @Value("${server.domain}")
    String serverDomain;
    @Autowired
    TopTiktokService topTiktokService;

    @Autowired
    BloggerService bloggerService;

    @Value("${jwt.head}")
    String authorized;

    @Autowired
    JwtUtil jwtUtil;

    @Autowired
    CommonService commonService;

    @Autowired
    ComparisonService comparisonService;

    @Autowired
    ChallengeService challengeService;

    @Autowired
    RedisTemplate<String, Object> redisObjectTemplate;

    @Autowired
    RankingService rankingService;

    @Autowired
    UserService userService;

    @Autowired
    UserRoleRepository userRoleRepository;

    /**
     * 官网热门音乐服务
     */
    @Autowired
    TopTiktokSoundService topTiktokSoundService;

    @Autowired
    ProductService productService;

    private int loadCount = 10;

    private String [] bloggerSorKey = new String[]{"gdindex","followers","likes","posts"};
    private String [] bloggerSorStr = new String[]{"GD Index","Followers","Likes","Posts"};
    /*private String [] bloggerSorKey = new String[]{"gdindex","followers","posts"};
    private String [] bloggerSorStr = new String[]{"GD Index","Followers","Posts"};*/
    private String [] videoSorKey = new String[]{"spreadIndex","view","likes","reviews","share"};
    private String [] videoSorStr = new String[]{"Spread Index","View","Likes","Reviews","Share"};
    private String [] videoTileStr = new String[]{"Popular","Viewed","Liked","Reviewed","Shared"};
    private String [] videoTypeKey = new String[]{"all","Dance","Handsome","Pretty","Beauty & Makeup","Arts","Animals"};
    private String [] videoTypeStr = new String[]{"All","Dance","E-Boy","E-Girl","Makeup","Arts","Animals"};
    private String [] videoTypeTileStr = new String[]{null,"Dance","E-Boy","E-Girl","Makeup","Paintings","Cat and Dog"};
    List<BloggerType> typeList = new ArrayList<>();


    @PostConstruct
    public void postConstruct(){
        BloggerType type = new BloggerType();
        type.setName("All");
        type.setId(0);
        typeList.add(type);
        typeList.addAll(bloggerService.getTypeList().subList(0, 6));
    }


    //####################################################TikTok达人 START####################################################

    @GetMapping("/influencer/{sort}")
    public ModelAndView influencerBySort(@PathVariable String sort){
        return getInfluencerModel(sort,null);
    }

    @GetMapping("/influencer/{sort}/{region}")
    public ModelAndView influencerBySortAndRegion(@PathVariable String sort,@PathVariable String region){
        return getInfluencerModel(sort,region);
    }

    private TopDescription titleDescription(String sortKey,String regionKey){
        String title = "Top TikTokers - Most Famous%s";
        String subTitle = "It's a list of popular TikTokers who are the most famous on TikTok%s.";

        switch (sortKey){
            case "gdindex":
                break;
            case "followers":
                title = "Top TikTokers - Most Followers%s";
                subTitle = "It's a list of popular TikTokers who have the most followers on TikTok%s.";
                break;
            case "likes":
                title = "Top TikTokers - Most Likes%s";
                subTitle = "It's a list of popular TikTokers who have the most likes on TikTok%s.";
                break;
            case "posts":
                title = "Top TikTokers - Most Posts%s";
                subTitle = "It's a list of popular TikTokers who have the most posts on TikTok%s.";
                break;
            default:
                break;
        }

        String regionStr = "";

        if(!StringUtils.isEmpty(regionKey)){
            for (RegionResponse regionResponse : commonService.allRegions) {
                if(regionResponse.getCode().equals(regionKey)){
                    regionStr = " in "+regionResponse.getName();
                    break;
                }
            }
        }
        TopDescription topDescription = new TopDescription();
        topDescription.setTitle(String.format(title, regionStr));
        topDescription.setSubtitle(String.format(subTitle, regionStr));
        return topDescription;
    }

    private ModelAndView getInfluencerModel(String sort,String region){
        ModelAndView modelAndView = new ModelAndView("/influencer/index");
        List<SortDto> sorts = getBloggerSorts(sort);
        modelAndView.addObject("sortList",sorts);
        modelAndView.addObject("isMobile", CheckMobile.check());

        SortDto sortObject = getCurSorts(sorts);

        if(sortObject.getKey().equals("gdindex")){
            sortObject.setKey("frame");
            sortObject.setName("Famous");
        }else if(sortObject.getKey().equals("followers")){
            sortObject.setKey("followers");
            sortObject.setName("Followed");
        }
        modelAndView.addObject("curSort",sortObject);
        modelAndView.addObject("curSortKey",sort);
        modelAndView.addObject("tab", Tab.TIKTOK_TOP_INFLUENTIAL.getValue());
        modelAndView.addObject("time", DateUtil.format(new Date(),"yyyy"));
        modelAndView.addObject("contextPath",serverDomain);

        RegionResponse regionResponse = null;

        List<RegionResponse> regionResponses = commonService.allRegions;
        if(!StringUtils.isEmpty(region)){
            for (RegionResponse r : regionResponses) {
                if(region.equals(r.getCode())){
                    regionResponse = r;
                    break;
                }
            }
        }
        modelAndView.addObject("curRegion",regionResponse);
        UserReturnDto user = getUser();
        modelAndView.addObject("login", user != null);
        modelAndView.addObject("user", user);
        modelAndView.addObject("regionList",regionResponses);
        val topDescription = titleDescription(sort, region);
        modelAndView.addObject("titleDescription",topDescription);
        modelAndView.addObject("dataList", topTiktokService.getBloggersForInfluencer(loadCount,sort,region));
        return modelAndView;
    }


    private List<SortDto> getBloggerSorts(String sortKey){
        List<SortDto> sorts = new ArrayList<>();
        for (int i = 0; i < bloggerSorKey.length; i++) {
            SortDto sort = new SortDto();
            sort.setKey(bloggerSorKey[i]);
            sort.setName(bloggerSorStr[i]);
            if(sortKey.equals(sort.getKey())) {
                sort.setActive(true);
            }
            sorts.add(sort);
        }
        return sorts;
    }

    /**
     * 获取博主粉丝画像数据示例数据
     * @return
     */
    @ApiOperation(value = "获取博主粉丝画像示例数据")
    @GetMapping(value = "/influencerDetail/fansPortrait")
    @ResponseBody
    public String getBloggerFansPortrait() {
        return Ret.success("success",topTiktokService.getBloggerFansPortrait());
    }

    @ApiOperation(value = "获取博主指标信息示例数据")
    @GetMapping(value = "/influencerDetail/quota")
    @ResponseBody
    public String getBloggerData(){
        return Ret.success("success",topTiktokService.getBloggerData());
    }

    @ApiOperation(value = "获取博主信息走趋示例数据")
    @GetMapping(value = "/influencerDetail/performance")
    @ResponseBody
    public String getBloggerPerformance(){
        return Ret.success("success",topTiktokService.getBloggerPerformance());
    }

    @ApiOperation(value = "获取博主视频信息走趋示例数据")
    @GetMapping(value = "/influencerDetail/aweme/performance")
    @ResponseBody
    public String getBloggerAwemePerformance(){
        return Ret.success("success",topTiktokService.getBloggerAwemePerformance());
    }

    //####################################################TikTok达人 END####################################################

    //####################################################热门视频 START####################################################
    @GetMapping("/video/{sort}/{type}")
    public ModelAndView videoBySort(@PathVariable String sort,@PathVariable String type){
        ModelAndView modelAndView = new ModelAndView("/video/index");
        List<SortDto> sorts = getVideoSorts(sort);
        modelAndView.addObject("tab",Tab.TIKTOK_HTO_VIDEO.getValue());

        modelAndView.addObject("isMobile", CheckMobile.check());
        // 排序列表
        modelAndView.addObject("sortList",sorts);
        // 类型列表
        List<SortDto> types = getVideoTypes(type);
        modelAndView.addObject("typeList",types);
        // 当前排序KEY
        modelAndView.addObject("curSortKey",sort);
        SortDto sortObject = null;

        for (int i = 0; i < videoSorKey.length; i++) {
            if(videoSorKey[i].equals(sort)){
                sortObject = new SortDto();
                sortObject.setName(videoTileStr[i]);
                sortObject.setKey(videoTileStr[i].toLowerCase());
                break;
            }
        }
        // 当前排序对象
        modelAndView.addObject("curSort",sortObject);
        // 当前年份
        modelAndView.addObject("time", DateUtil.format(new Date(),"yyyy"));
        // 当前类型KEY
        modelAndView.addObject("curTypeKey",type);
        SortDto curType = getCurSorts(types);

        if(null != curType){
            if(curType.getKey().equals(videoTypeKey[0])){
                curType = null;
            }
        }
        modelAndView.addObject("curType",curType);
        String titleStr = getVideoTileStr(type);
        modelAndView.addObject("titleStr",titleStr);
        UserReturnDto user = getUser();
        modelAndView.addObject("login", user != null);
        modelAndView.addObject("user", user);
        modelAndView.addObject("contextPath",serverDomain);
        modelAndView.addObject("titleDescription",videoDescription(sort,titleStr == null? "":titleStr));
        modelAndView.addObject("dataList", topTiktokService.getBastVideo(loadCount,sort,type.equals(videoTypeKey[0])?null:type));
        return modelAndView;
    }

    private List<SortDto> getVideoTypes(String typeKey){
        List<SortDto> sorts = new ArrayList<>();
        for (int i = 0; i < videoTypeKey.length; i++) {
            SortDto sort = new SortDto();
            sort.setKey(videoTypeKey[i]);
            sort.setName(videoTypeStr[i]);
            if(typeKey.equals(sort.getKey())) {
                sort.setActive(true);
            }
            sorts.add(sort);
        }
        return sorts;
    }

    private String getVideoTileStr(String typeKey){
        for (int i = 0; i < videoTypeKey.length; i++) {
            if(typeKey.equals(videoTypeKey[i])) {
                return videoTypeTileStr[i];
            }
        }
        return videoTypeTileStr[0];
    }

    private List<SortDto> getVideoSorts(String sortKey){
        List<SortDto> sorts = new ArrayList<>();
        for (int i = 0; i < videoSorKey.length; i++) {
            SortDto sort = new SortDto();
            sort.setKey(videoSorKey[i]);
            sort.setName(videoSorStr[i]);
            if(sortKey.equals(sort.getKey())) {
                sort.setActive(true);
            }
            sorts.add(sort);
        }
        return sorts;
    }

    private SortDto getCurSorts(List<SortDto> sorts){
        for (SortDto sort : sorts) {
            if(sort.isActive()){
                return ObjectUtil.cloneByStream(sort);
            }
        }
        return null;
    }


    private TopDescription videoDescription(String sortKey,String type){
        String title = "Best TikTok %sVideo - Most Popular";
        String subTitle = "It's a list of most popular %svideo on TikTok lately.";

        switch (sortKey){
            case "gdindex":
                break;
            case "view":
                title = "Best TikTok %sVideo - Most Viewed";
                subTitle = "It's a list of most viewed %svideos on TikTok lately.";
                break;
            case "likes":
                title = "Best TikTok %sVideo - Most Liked";
                subTitle = "It's a list of most liked %svideos on TikTok lately.";
                break;
            case "reviews":
                title = "Best TikTok %sVideo - Most Reviewed";
                subTitle = "It's a list of most reviewed %svideos on TikTok lately.";
                break;
            case "Share":
                title = "Best TikTok %sVideo - Most Shared";
                subTitle = "It's a list of most shared %svideos on TikTok lately.";
                break;
            default:
                break;
        }


        if(StringUtils.isEmpty(type) || type.equals(videoTypeKey[0])){
            type = "";
        }

        TopDescription topDescription = new TopDescription();
        topDescription.setTitle(String.format(title, type+" "));
        topDescription.setSubtitle(String.format(subTitle, type.toLowerCase()+" "));
        return topDescription;
    }


    //####################################################热门视频 END####################################################


    //####################################################Tiktok播主详情 START####################################################
    @GetMapping("/tiktoker/{uniqueId}")
    public ModelAndView getBloggerDetailInfo(@PathVariable String uniqueId){
        ModelAndView modelAndView = new ModelAndView("/tiktoker/index");
        modelAndView.addObject("tab",Tab.TIKTOK_BLOGGER_DETAIL.getValue());
        modelAndView.addObject("contextPath",serverDomain);

        modelAndView.addObject("isMobile", CheckMobile.check());
        UserReturnDto user = getUser();
        modelAndView.addObject("login", user != null);
        modelAndView.addObject("user", user);
        BloggerDto bloggerDto = getBloggerByUniqueId(uniqueId);
        modelAndView.addObject("blogger",bloggerDto);
        modelAndView.addObject("bloggers",getRandomBloggerDtos(CheckMobile.check()));
        modelAndView.addObject("videos",topTiktokService.getVideoByUid(bloggerDto.getUid()));
        modelAndView.addObject("videoTotalSize",topTiktokService.getVideoTotalSizeByUid(bloggerDto.getUid()));
        BloggerPerformanceDto weekBloggerPerformanceDto = (BloggerPerformanceDto)redisObjectTemplate.opsForValue().get("example_week_blogger");
        BloggerPerformanceDto monthBloggerPerformanceDto = (BloggerPerformanceDto)redisObjectTemplate.opsForValue().get("example_month_blogger");

        if(null == weekBloggerPerformanceDto || null == monthBloggerPerformanceDto){
            weekBloggerPerformanceDto = new BloggerPerformanceDto();
            monthBloggerPerformanceDto = new BloggerPerformanceDto();
            Blogger blogger = JdbcTemplateHelper.findFirstEntity(Blogger.class,"select o_uid from blogger_main where o_uid = 6703550784929793030");
            BloggerDataResponse weekBloggerData = bloggerService.getBloggerData(blogger.getOUid(),6);
            List<BloggerPerformanceResponse> weekBloggerPerformance = bloggerService.getBloggerPerformance(blogger.getOUid(),6);
            List<AwemeResponse> weekAweme = bloggerService.getBloggerAwemePerformance(blogger.getOUid(),6);
            weekBloggerPerformanceDto.setBloggerDataResponse(weekBloggerData);
            weekBloggerPerformanceDto.setBloggerPerformanceResponse(weekBloggerPerformance);
            weekBloggerPerformanceDto.setAwemeResponse(weekAweme);
            redisObjectTemplate.opsForValue().set("example_week_blogger",weekBloggerPerformanceDto,1, TimeUnit.DAYS);
            BloggerDataResponse monthBloggerData = bloggerService.getBloggerData(blogger.getOUid(),29);
            List<BloggerPerformanceResponse> monthBloggerPerformance = bloggerService.getBloggerPerformance(blogger.getOUid(),29);
            List<AwemeResponse> monthAweme = bloggerService.getBloggerAwemePerformance(blogger.getOUid(),29);
            monthBloggerPerformanceDto.setBloggerDataResponse(monthBloggerData);
            monthBloggerPerformanceDto.setBloggerPerformanceResponse(monthBloggerPerformance);
            monthBloggerPerformanceDto.setAwemeResponse(monthAweme);
            redisObjectTemplate.opsForValue().set("example_month_blogger",monthBloggerPerformanceDto,1, TimeUnit.DAYS);
        }
        modelAndView.addObject("weekExampleData",weekBloggerPerformanceDto);
        modelAndView.addObject("monthExampleData",monthBloggerPerformanceDto);
        // 是否解锁过
        boolean isUnlock = false;

        if(null != getUser()){
            isUnlock = productService.isUnlocked(getUser().getId(),bloggerDto.getUid(), PlatformTypeEnum.TIKTOK.getCode());
            // 未解锁并是豪华版以上的用户自动解锁
            long roleId = getRoleId(user);
            if(isUnlock == false && roleId > 2){
                // 角色剩余次数
                int unlockCount = productService.unlockedNumberByRole(user.getId(),roleId,ReportTypeEnum.BLOGGER.getMsg());
                // 报告次数
                if(unlockCount < 1){
                    unlockCount = productService.unlockedNumberByReportStarter(user.getId());
                }
                // 角色解锁
                if(unlockCount > 0){
                    isUnlock = productService.unlockedByUserRole(user.getId(),roleId,bloggerDto.getUid(),PlatformTypeEnum.TIKTOK.getCode(), ReportTypeEnum.BLOGGER.getCode(), ReportTypeEnum.BLOGGER.getMsg());
                }
                // 报告解锁
                if(!isUnlock){
                    isUnlock = productService.unlockedByReportStarter(user.getId(),bloggerDto.getUid(), PlatformTypeEnum.TIKTOK.getCode(), ReportTypeEnum.BLOGGER.getCode());
                }
                // 更新用户信息
                if(isUnlock){
                    modelAndView.addObject("user",getUser());
                }
            }
        }
        modelAndView.addObject("isUnlocked",isUnlock);
        modelAndView.addObject("myController",this);

        return modelAndView;
    }

    @GetMapping("/tiktoker/video/{uniqueId}")
    public ModelAndView getBloggerVideo(@PathVariable String uniqueId){
        ModelAndView modelAndView = new ModelAndView("/tiktoker/video/index");
        BloggerDto bloggerDto = getBloggerByUniqueId(uniqueId);

        modelAndView.addObject("isMobile", CheckMobile.check());
        modelAndView.addObject("tab",5);
        modelAndView.addObject("contextPath",serverDomain);
        UserReturnDto user = getUser();
        modelAndView.addObject("login", user != null);
        modelAndView.addObject("user", user);
        modelAndView.addObject("blogger",bloggerDto);
        modelAndView.addObject("bloggers",getRandomBloggerDtos(CheckMobile.check()));
        modelAndView.addObject("videos",topTiktokService.getVideoByUid(bloggerDto.getUid()));
        return modelAndView;
    }

    private List<BloggerDto> getRandomBloggerDtos(boolean mobile){
        int size = 10;

        if(mobile){
            size = 5;
        }
        List<Blogger> bloggers = bloggerService.getRandomBloggers(size);
        List<BloggerDto> bloggerDtos = new ArrayList<>();

        for (Blogger blogger : bloggers) {
            bloggerDtos.add(bloggerToBloggerDto(blogger));
        }
        return bloggerDtos;
    }

    private BloggerDto getBloggerByUniqueId(String uniqueId){
        Blogger blogger = bloggerService.getBloggerByUniqueId(uniqueId);
        return bloggerToBloggerDto(blogger);
    }

    private BloggerDto bloggerToBloggerDto(Blogger blogger){
        BloggerDto bloggerDto = new BloggerDto();
        bloggerDto.setAvatar(blogger.getOAvatar300());

        if((bloggerDto.getAvatar().indexOf("sign-sg") > 0 && bloggerDto.getAvatar().indexOf("sign-sg") < 30) || bloggerDto.getAvatar().indexOf("sign-va") > 0 && bloggerDto.getAvatar().indexOf("sign-va") < 30){
            bloggerDto.setAvatar(bloggerDto.getAvatar().replace("sign-sg", "amd-va").replace("sign-va", "amd-va").replace("webp", "jpeg"));
        }
        bloggerDto.setFollowerCount(getNumber(blogger.getOFollowerCount()));
        bloggerDto.setAvgViews(getNumber(blogger.getOAvgViews()));
        bloggerDto.setLikeCount(getNumber(blogger.getOTotalFavorited()));
        bloggerDto.setAvgLikes(getNumber(blogger.getOAvgLikes()));
        bloggerDto.setAvgReviews(getNumber(blogger.getOAvgReviews()));
        bloggerDto.setAvgShare(getNumber(blogger.getOAvgShare()));
        bloggerDto.setNickname(blogger.getONickname());
        bloggerDto.setUid(blogger.getOUid());
        bloggerDto.setUniqueId(blogger.getOUniqueId());
        bloggerDto.setSignature(blogger.getOSignature());
        bloggerDto.setScore(getNumber(blogger.getScore()));
        bloggerDto.setPostCount(getNumber(blogger.getOAwemeCount()));
        bloggerDto.setRegion(blogger.getORegion());
        bloggerDto.setEnterpriseVerifyRreason(blogger.getEnterpriseVerifyReason());
        bloggerDto.setCustomVerify(blogger.getCustomVerify());
        bloggerDto.setWithFusionShopEntry(blogger.getWithFusionShopEntry());
        bloggerDto.setYoutubeCchannelId(blogger.getYoutubeChannelId());
        bloggerDto.setTwitterId(blogger.getTwitterId());
        bloggerDto.setInsId(blogger.getInsId());
        bloggerDto.setBioEmail(blogger.getBioEmail());
        bloggerDto.setBioUrl(blogger.getBioUrl());

        if(!StringUtils.isEmpty(bloggerDto.getBioUrl())){
            if(!bloggerDto.getBioUrl().contains("www")){
                bloggerDto.setBioUrl("www."+bloggerDto.getBioUrl());
            }
        }


        bloggerDto.setUpdateTime(blogger.getUpdateTime());

        //设置播主当日全球排名
        int dateCode = Integer.parseInt(DateUtil.format(LocalDateTime.now().minusDays(1),"yyyyMMdd"));
        Ranking ranking = rankingService.getBloggerRanking(blogger.getOUid(), 1,0,dateCode);
        if(ranking != null){
            bloggerDto.setGlobalRank(ranking.getRanking());
        }

        BigDecimal dscCount = new BigDecimal(blogger.getOAvgLikes()+blogger.getOAvgShare()+blogger.getOAvgReviews());
        BigDecimal playCount = new BigDecimal(blogger.getOAvgViews());
        bloggerDto.setEngagementRate((dscCount.divide(playCount,3, RoundingMode.FLOOR).multiply(new BigDecimal(100))).setScale(1).doubleValue()+"%");
        return bloggerDto;
    }

    //####################################################Tiktok播主详情 END####################################################


    //####################################################Tiktok播主对比 START####################################################
    @GetMapping("/tiktoker/comparison")
    public ModelAndView getComparison() throws JsonProcessingException {
        ModelAndView modelAndView = new ModelAndView("/tiktoker/comparison/index");
        String rowJson = ResourceUtil.readUtf8Str("row.json");

        modelAndView.addObject("isMobile", CheckMobile.check());
        ObjectMapper mapper = new ObjectMapper();
        List<RowData> rowDatas = mapper.readValue(rowJson, new TypeReference<List<RowData>>(){});
        modelAndView.addObject("tab",Tab.TIKTOK_BLOGGER_COMPARISON.getValue());
        modelAndView.addObject("contextPath",serverDomain);
        UserReturnDto user = getUser();
        modelAndView.addObject("login", user != null);
        modelAndView.addObject("user", user);

        ComparisonHistory comparisonHistory = comparisonService.getNewComparisonHistory(0);

        if(null != comparisonHistory){
            int dataDateCode =  Integer.parseInt(LocalDateTime.ofInstant(Instant.ofEpochSecond(comparisonHistory.getUpdateTime()), ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("yyyyMMdd")));
            int todayDataCode = Integer.parseInt(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")));
            if(dataDateCode < todayDataCode){
                comparisonHistory = comparison();
            }
        }else {
            comparisonHistory = comparison();
        }
        val comparisonHistoryData = comparisonService.getComparisonHistoryData(comparisonHistory.getId());
        /*comparisonHistoryData.getComparisonHistoryDetails().forEach( comparisonHistoryDetail -> {

        });*/
        modelAndView.addObject("comparison",comparisonHistoryData);
        modelAndView.addObject("rows",rowDatas);
        modelAndView.addObject("myController",this);
        return modelAndView;
    }

    private ComparisonHistory comparison(){
        List<General> generals =  commonService.getGeneralByType("comparison");
        List<BloggerResponse> bloggerResponses = new ArrayList<>(generals.size());
        generals.forEach( general -> {
            BloggerResponse bloggerResponse = new BloggerResponse();
            bloggerResponse.setUid(general.getDynamicId());
            bloggerResponses.add(bloggerResponse);
        });
        ComparisonHistory comparisonHistory  = comparisonService.addComparisonHistory(0);
        comparisonService.generalHistoryDetail(bloggerResponses, comparisonHistory.getId(),0);
        return comparisonHistory;
    }
    //####################################################Tiktok播主对比 END####################################################


    //####################################################Tiktok标签 START####################################################
    @GetMapping("/tiktok/hashtags")
    public ModelAndView getHashtags() throws IOException {
        ModelAndView modelAndView = new ModelAndView("/tiktoker/hashtag/index");
        SearchData searchData = new SearchData();

        modelAndView.addObject("isMobile", CheckMobile.check());
        Page<ChallengeResponse> pageData = challengeService.getPageEs(searchData,null);
        modelAndView.addObject("tab",Tab.TIKTOK_TAG.getValue());
        modelAndView.addObject("contextPath",serverDomain);
        UserReturnDto user = getUser();
        modelAndView.addObject("login", user != null);
        modelAndView.addObject("user", user);
        modelAndView.addObject("dataList",pageData.getList());
        modelAndView.addObject("myController",this);
        modelAndView.addObject("curYear", String.valueOf(LocalDateTime.now().getYear()));
        return modelAndView;
    }

    @GetMapping("/tiktok/hashtags/{cid}")
    public ModelAndView getHashtagDetail(@PathVariable long cid) throws IOException {
        ModelAndView modelAndView = new ModelAndView("/tiktoker/hashtag/detail/index");
        modelAndView.addObject("tab",Tab.TIKTOK_TAG.getValue());
        modelAndView.addObject("isMobile", CheckMobile.check());
        modelAndView.addObject("contextPath",serverDomain);
        UserReturnDto user = getUser();
        modelAndView.addObject("login", user != null);
        modelAndView.addObject("user", user);
        modelAndView.addObject("challenge",challengeService.getChallenge(cid,null));
        modelAndView.addObject("videos",challengeService.getAwemePageByChallenge(cid, 0, 1, 10, null).getList());
        modelAndView.addObject("region",challengeService.getRegionDistribution(cid));
        modelAndView.addObject("industry",challengeService.getIndustryDistribution(cid));
        modelAndView.addObject("myController",this);
        SearchData searchData = new SearchData();
        Random r = new Random();
        int size = r.nextInt(500);
        searchData.setPage(size);

        Page<ChallengeResponse> pageData = challengeService.getPageEs(searchData,null);
        modelAndView.addObject("challenges",pageData.getList());
        return modelAndView;

    }
    //####################################################Tiktok标签 END####################################################

    //####################################################Tiktok博主搜索 START####################################################
    @RequestMapping(value = "tiktoker/search", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
    @ResponseBody
    public String searchBlogger(String keyword){
        return Ret.success("success",topTiktokService.searchBlogger(keyword));
    }
    //####################################################Tiktok博主搜索 END####################################################

    //#####################################Tiktok热门音乐 START######################

    /**
     * 官网热门音乐信息页
     * 在es中根据userGrowth（用户增长数）查询前10条音乐的相关数据
     * @return ModelAndView
     */
    @ApiOperation(value = "前10条热门音乐列表")
    @GetMapping(value = "/tiktok/sounds")
    public ModelAndView getTopSoundList(){
        // 跳转模板页面
        ModelAndView modelAndView = new ModelAndView("/sound/index");
        //添加tab
        modelAndView.addObject("tab",Tab.TIKTOK_MUSIC.getValue());
        modelAndView.addObject("isMobile", CheckMobile.check());
        // 当前年份
        modelAndView.addObject("time", DateUtil.format(new Date(),"yyyy"));
        //登入信息
        UserReturnDto user = getUser();
        modelAndView.addObject("login", user != null);
        modelAndView.addObject("user", user);
        //域名
        modelAndView.addObject("contextPath",serverDomain);
        //转递类方法
        modelAndView.addObject("myController",this);

        //查询es前10条人们音乐结果
        List<SoundResponse> dataList = topTiktokSoundService.getTopTiktokSoundListByEs(null,null);
        //返回热门音乐前10条数据查询的数据
        modelAndView.addObject("dataList", dataList);

        return modelAndView;
    }

    /**
     * 官网热门音乐详情页
     * 根据mid获取音乐详情信息
     * 根据mid获取相关视频信息
     * 调用getTopTiktokSoundListByEs随机获取10条音乐数据
     * @mid
     * @return ModelAndView
     */
    @ApiOperation(value = "热门音乐详情")
    @GetMapping(value = "/tiktok/sounds/{mid}")
    public ModelAndView getTopSoundDetail(@PathVariable long mid){
        // 跳转模板页面
        ModelAndView modelAndView = new ModelAndView("/sound/detail/index");
        //添加tab
        modelAndView.addObject("tab",Tab.TIKTOK_MUSIC.getValue());
        modelAndView.addObject("isMobile", CheckMobile.check());
        //登入信息
        UserReturnDto user = getUser();
        modelAndView.addObject("login", user != null);
        modelAndView.addObject("user", user);
        //域名
        modelAndView.addObject("contextPath",serverDomain);
        //音乐详情
        modelAndView.addObject("musicDetail", topTiktokSoundService.getMusicDetailByEs(mid));
        //相关视频
        modelAndView.addObject("videos", topTiktokSoundService.getAwemeByMusic(mid));
        //推荐音乐
        modelAndView.addObject("recommendedMusic", topTiktokSoundService.getRecommendedMusic(mid,10));
        //转递类方法
        modelAndView.addObject("myController",this);

        return modelAndView;
    }

    //#####################################Tiktok热门音乐 END######################

    public String getNumber(long num) {
        return topTiktokService.getNumber(num);
    }

    public String getNumber(double num) {
        return topTiktokService.getNumber(num);
    }

    public String dateTrans(long second){
        return LocalDateTime.ofInstant(Instant.ofEpochSecond(second), ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("MM-dd-yyyy HH:mm:ss"))+" UTC";
    }

    private UserReturnDto getUser() {
        String token = HttpUtil.getCookie(authorized);

        if (StringUtils.isEmpty(token)) {
            return null;
        }
        User user = JsonUtil.jsonParse(User.class, JsonUtil.parseJson(jwtUtil.getJwtUser(token).getUser()));
        return userService.getUser(user.getId());
    }

    protected long getRoleId(UserReturnDto user){
        long roleId = 1;

        val userRoleOptional = userRoleRepository.findTop1ByUserIdAndExpireTimeGreaterThanEqualOrderByRoleIdDesc(user.getParentId() == 0 ?user.getId():user.getParentId(), new Date());

        if(userRoleOptional.isPresent()){
            roleId = userRoleOptional.get().getRoleId();
        }
        return roleId;
    }

    @Data
    public class TopDescription{
        private String title;
        private String subtitle;
    }


}
